#include "demo_utils.hpp"

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

namespace atomic_examples {
namespace {

/**
 * @brief 基于 std::atomic_flag 的简易自旋锁实现。
 *
 * 适用场景：
 *  - 临界区极短，且期待在高并发下避免 OS 线程切换。
 *  - 需要比 std::mutex 更轻量的同步原语。
 *
 * ⚠️ 注意：
 *  - 自旋锁在高争用下会消耗大量 CPU；应谨慎使用，并在循环中调用 yield/backoff。
 */
class SpinLock {
public:
  /**
   * @brief 加锁操作。
   *
   * 若锁已被其他线程持有，则调用线程会自旋等待直至成功抢到锁。
   */
  void lock() {
    while (flag_.test_and_set(std::memory_order_acquire)) {
      std::this_thread::yield();  ///< 防止自旋锁占满 CPU。
    }
  }

  /**
   * @brief 解锁操作。
   *
   * 清除标志位，允许其他线程进入临界区。
   */
  void unlock() {
    flag_.clear(std::memory_order_release);
  }

private:
  std::atomic_flag flag_ = ATOMIC_FLAG_INIT; ///< 原子标志，true 表示锁已被持有。
};

/**
 * @brief 演示使用自旋锁保护共享计数器。
 */
void runSpinLockDemo() {
  printHeader("SpinLock Example");

  SpinLock lock;
  int shared_counter = 0; ///< 需要保护的共享资源。

  auto worker = [&]() {
    for (int i = 0; i < 100'000; ++i) {
      lock.lock();
      ++shared_counter;
      lock.unlock();
    }
  };

  std::vector<std::thread> threads;
  threads.reserve(4);
  for (int i = 0; i < 4; ++i) {
    threads.emplace_back(worker);
  }
  for (auto& t : threads) {
    t.join();
  }

  std::cout << "Counter guarded by SpinLock: " << shared_counter << '\n';
}

} // namespace
} // namespace atomic_examples

int main() {
  atomic_examples::runSpinLockDemo();
  return 0;
}